package h5

import (
	. "chess_platform/internal/common"
	"chess_platform/models/client"
	"chess_platform/models/h5"
	"fmt"
	"github.com/astaxie/beego/orm"
	"time"
)

//[h5]钻石
type CardController struct {
	GrantController
}

func (b *CardController) URLMapping() {
	b.Mapping("StatPlayerCard", b.StatPlayerCard)
	b.Mapping("StatCard", b.StatCard)
	b.Mapping("List", b.List) //代理的钻石买卖流水
	b.Mapping("GiveCard", b.GiveCard)
	b.Mapping("ListAgentPlayer", b.ListAgentPlayer)
	b.Mapping("HandleTopUp", b.HandleTopUp)
	b.Mapping("ListCard", b.ListCard)
	b.Mapping("ListGiveCard", b.ListGiveCard)
	b.Mapping("ListAutoCard", b.ListAutoCard)

}

// @Title 一级代理获取二级代理名下玩家充值列表
// @Description 统计二级代理买卡最多，直充最多，代充最多
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Param   type         body   int     false      "1-买卡最多,2-代充最多,3-直充最多"
// @Success 0 {object} []common.StatAgentPlayer 玩家充值列表
// @router /stat-player-card [post]
func (b *CardController) StatPlayerCard() {
	type Params struct {
		ListParams
		Type int64 `json:"type" valid:"Range(1,3)"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	count, err := h5.StatPlayerCardCount(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if count.TotalPlayerCount == 0 { //没有玩家充值过
		b.Res.Code = ErrNoData
		b.Res.Msg = MsgErrNoData
		b.Response()
		return
	}

	var (
		handle []*StatAgentPlayer
		auto   []*StatAgentPlayer
		total  []*StatAgentPlayer
		result []*StatAgentPlayer
	)
	switch p.Type {
	case HandleTopUp:
		//handle已经是排好序的了
		handle, err = h5.StatPlayerCardInfo(p.ListParams, p.Type, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		p.Type = AutomaticTopUp
		auto, err = h5.StatPlayerCardInfo(p.ListParams, p.Type, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		autoMap := make(map[int64]*StatAgentPlayer, 0)
		for _, v := range auto {
			autoMap[v.Uid] = v
		}
		for _, v := range handle {
			a, ok := autoMap[v.Uid]
			if ok {
				v.AutomaticCount = a.AutomaticCount
				delete(autoMap, v.Uid)
			}
		}

		for _, v := range autoMap {
			handle = append(handle, v)
		}
		result = handle

	case AutomaticTopUp:
		//auto已经是排好序的了
		auto, err = h5.StatPlayerCardInfo(p.ListParams, p.Type, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		p.Type = HandleTopUp
		handle, err = h5.StatPlayerCardInfo(p.ListParams, p.Type, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		handleMap := make(map[int64]*StatAgentPlayer, 0)
		for _, v := range handle {
			handleMap[v.Uid] = v
		}
		for _, v := range auto {
			h, ok := handleMap[v.Uid]
			if ok {
				v.HandleCount = h.HandleCount
				delete(handleMap, v.Uid)
			}
		}

		for _, v := range handleMap {
			auto = append(auto, v)
		}
		result = auto
	default:
		//已经是排好序的了,买卡最多
		total, err = h5.StatPlayerCardInfo(p.ListParams, p.Type, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}

		p.Type = AutomaticTopUp
		auto, err = h5.StatPlayerCardInfo(p.ListParams, p.Type, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		p.Type = HandleTopUp
		handle, err = h5.StatPlayerCardInfo(p.ListParams, p.Type, b.Uid)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		handleMap := make(map[int64]*StatAgentPlayer, 0)
		autoMap := make(map[int64]*StatAgentPlayer, 0)
		for _, v := range auto {
			autoMap[v.Uid] = v
		}
		for _, v := range handle {
			handleMap[v.Uid] = v
		}
		for _, v := range total {
			h, ok := handleMap[v.Uid]
			if ok {
				v.HandleCount = h.HandleCount
			}
			a, ok := autoMap[v.Uid]
			if ok {
				v.AutomaticCount = a.AutomaticCount
			}
		}
		result = total

	}
	field := []string{"uid,nickname,imageurl"}
	o := orm.NewOrm()
	o.Using(DBChess)
	for _, v := range result {
		u, err := client.SpecifyUserInfoById(v.Uid, field, o)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		if u == nil {
			LogH5.Notice(fmt.Sprintf("h5代理充值列表里有玩家ID:%v 而client里没有,数据库肯定出错了", v.Uid))
		} else {
			v.HeadImgUrl = u.ImageUrl
			v.Nickname = u.Nickname
		}
	}

	b.Res.Data = result
	b.Res.Count = count
	b.ResponseSuccess()
	return
}

// @Title 统计当前代理累计买，累计卖了多少张钻石,剩余钻石数
// @Description 统计当前代理累计买，累计卖了多少张钻石,剩余钻石数
// @Success 0 {object} common.StatCard
// @router /stat-card [post]
func (b *CardController) StatCard() {
	stat, err := h5.StatCardInfo(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = stat
	b.ResponseSuccess()
}

// @Title 钻石买卖流水
// @Description 钻石买卖流水
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Param   type         body   int     false      "1-买房卡,2-卖房卡(代充),3-卖房卡(直充),4-送房卡,5-获赠房卡,6-系统赠送"
// @Param   player_id    body   int     false      "搜索玩家id"
// @Success 0 {object} []common.CardRecord 钻石流水列表
// @router /list [post]
func (b *CardController) List() {
	var p ListCardParams
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}

	cr, count, err := h5.ListCardRecord(p, b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = cr
	b.Res.Count = count
	b.ResponseSuccess()
}

// @Title 赠送钻石
// @Description 赠送钻石
// @Param   id    body    int true      "赠送钻石数量对应列表的id"
// @Param   uid   body    int true      "被赠送人的id"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /give-card [post]
func (b *CardController) GiveCard() {
	type Params struct {
		Uid int64 `json:"uid" valid:"Required"`
		Id  int64 `json:"id" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	card, err := h5.CardById(p.Id, AgentGiveCard)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if card == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		b.Response()
		return
	}

	//先判断下获赠人是否已经激活了成为正式代理了，如果不是不能获赠
	field := []string{"status"}
	ru, err := h5.SpecifyUserInfoById(p.Uid, field)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if ru == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		LogH5.Error(fmt.Sprintf("获赠代理:%d在表%v没有记录", p.Uid, TableH5CardCash))
		b.Response()
		return
	}
	if ru.Status != FirstTopUpSuccess {
		b.Res.Code = ErrAgentInactive
		b.Res.Msg = MsgErrAgentInactive
		b.Response()
		return
	}

	//首先判断下赠送者的钻石数量够不够赠送
	cc, err := h5.CardCashById(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if cc.Uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		LogH5.Error(fmt.Sprintf("代理:%d在表%v没有记录", b.Uid, TableH5CardCash))
		b.Response()
		return
	}

	if cc.CardNum < card.Num {
		b.Res.Code = ErrCardNotEnough
		b.Res.Msg = MsgErrCardNotEnough
		b.Response()
		return
	}

	o := orm.NewOrm()
	o.Using(DBChessCenter)
	o.Begin()
	defer o.Rollback()
	//减去赠送人的钻石数量
	gn, err := h5.UpdateCard(-card.Num, b.Uid, false, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if gn == 0 {
		o.Rollback()
		msg := fmt.Sprintf("代理:%d赠送钻石在减少钻石数:%d时失败", b.Uid, card.Num)
		LogH5.Notice(msg)
		b.ResponseFail("赠送钻石失败")
		return
	}

	//加上获赠送人的钻石数量
	rn, err := h5.UpdateCard(card.Num, p.Uid, false, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))

		return
	}
	if rn == 0 {
		o.Rollback()
		msg := fmt.Sprintf("代理:%d赠送给代理:%d钻石在加上钻石数:%d时失败", b.Uid, p.Uid, card.Num)
		LogH5.Notice(msg)
		b.ResponseFail("赠送钻石失败")
		return
	}
	//赠送人的角度
	giveCR := map[string]interface{}{
		"agent_id":    b.Uid,
		"player_id":   p.Uid,
		"card_num":    -card.Num,
		"type":        GiveRoomCard,
		"create_time": time.Now().Unix(),
	}
	//获赠人的角度
	receiveCR := map[string]interface{}{
		"agent_id":    p.Uid,
		"player_id":   b.Uid,
		"card_num":    card.Num,
		"type":        ReceiveRoomCard,
		"create_time": time.Now().Unix(),
	}
	_, err = h5.NewCardRecord(giveCR, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	_, err = h5.NewCardRecord(receiveCR, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	o.Commit()
	b.ResponseSuccess()
}

// @Title 获取玩家列表
// @Description 在一段时间内在此代理充值过的玩家列表
// @Param   page_size    body   int     true       "每页显示数量"
// @Param   page_index   body   int     true       "第几页"
// @Success 0 {object} []common.AgentPlayer 玩家列表
// @router /list-agent-player [post]
func (b *CardController) ListAgentPlayer() {
	var p ListParams
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	play, count, err := h5.ListAgentPlayer(p, b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if count == 0 {
		b.Res.Code = ErrNoData
		b.Res.Msg = MsgErrNoData
		b.Response()
		return
	}
	o := orm.NewOrm()
	o.Using(DBChess)
	for _, v := range play {
		u, err := client.QueryUserInfoById(v.PlayerId, o)
		if err != nil {
			LogH5.Error(b.DatabaseError(err.Error()))
			return
		}
		v.Nickname = u.Nickname
		v.HeadImgUrl = u.ImageUrl
	}
	b.Res.Data = play
	b.Res.Count = count
	b.ResponseSuccess()
}

// @Title 代充钻石
// @Description 代充钻石
// @Param   num         body    int true      "钻石数量"
// @Param   player_id   body    int true      "玩家id"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /handle-top-up [post]
func (b *CardController) HandleTopUp() {
	type Params struct {
		Num      int64 `json:"num"`
		PlayerId int64 `json:"player_id"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	//最小充值数量为1
	b.Valid.Min(p.Num, 1, "num").Message("请输入有效的充值数量")
	b.Valid.Required(p.PlayerId, "player_id").Message("请输入充值玩家ID")
	if !b.VerifyParamsError() {
		return
	}
	dbUser, err := client.QueryUserInfoById(p.PlayerId)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if dbUser.Uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = fmt.Sprintf("玩家ID:%v不存在,请检查", p.PlayerId)
		b.Response()
		return
	}

	//首先判断下代理的钻石数量够不够充值
	cc, err := h5.CardCashById(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	if cc.Uid == 0 {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		LogH5.Error(fmt.Sprintf("代理:%d在表%v没有记录", b.Uid, TableH5CardCash))
		b.Response()
		return
	}
	//判断钻石够不够
	if cc.CardNum < p.Num {
		b.Res.Code = ErrCardNotEnough
		b.Res.Msg = MsgErrCardNotEnough
		b.Response()
		return
	}
	ok := client.ChangeAccountValueFromLobby(p.PlayerId, p.Num,
		0, 0, ACCTRAN_OPER_TYPE_BuyCard, 0)
	if !ok {
		eventLog := map[string]interface{}{
			"module":     ModuleSystem,
			"event_type": EventPlay,
			"user_type":  Player,
			"uid":        p.PlayerId,
			"msg":        fmt.Sprintf("游戏服返回失败,代充失败,请联系开发人员"),
		}
		go NewEventLog(eventLog)
		b.ResponseFail("代充失败,系统错误")
		LogH5.Error("游戏服返回失败,代充钻石失败")
		return
	}

	o := NewDBOrm(DBChessCenter)
	o.Begin()
	defer o.Rollback()
	//减去代理的钻石数量, p.Num是一个正数
	_, err = h5.UpdateCard(-p.Num, b.Uid, false, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}

	//代充记录
	handleCR := map[string]interface{}{
		"agent_id":    b.Uid,
		"player_id":   p.PlayerId,
		"card_num":    -p.Num,
		"type":        HandleTopUp,
		"create_time": time.Now().Unix(),
	}

	_, err = h5.NewCardRecord(handleCR, o)
	if err != nil {
		o.Rollback()
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	o.Commit()
	b.ResponseSuccess()
	//凡是在此代理充值过的玩家，不管是直充还是代充，都要记录到表里
	agentPlayer := map[string]interface{}{
		"create_time": time.Now().Unix(),
	}
	//不用管成功与否，不重要
	h5.UpdateOrInsertAgentPlayer(agentPlayer, p.PlayerId, b.Uid)
}

// @Title 代理进货时看到钻石列表
// @Description 代理进货时看到钻石列表
// @Success 0 {object} []common.Card
// @router /list-card [post]
func (b *CardController) ListCard() {
	var (
		card []Card
		err  error
	)
	if b.Level == Level1 && h5.Level1AgentIsPass(b.Uid) { //一级且考核通过
		card, err = h5.ListCard(RuleLevel1CardPrice)
	} else { //一级考核不通过，或二级
		card, err = h5.ListCard(RuleLevel2CardPrice)
	}
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = card
	b.ResponseSuccess()
}

// @Title 代理赠送钻石时看到钻石列表
// @Description 代理赠送钻石时看到钻石列表
// @Success 0 {object} []common.Card
// @router /list-give-card [post]
func (b *CardController) ListGiveCard() {
	card, err := h5.ListCard(AgentGiveCard)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	restCard, err := h5.RestCard(b.Uid)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	data := map[string]interface{}{
		"rest_card": restCard,
		"list":      card,
	}
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 玩家直充时看到钻石列表
// @Description 玩家直充时看到钻石列表
// @Success 0 {object} []common.Card 玩家直充钻石列表
// @router /list-auto-card [post]
func (b *CardController) ListAutoCard() {
	card, err := h5.ListCard(RulePlayerCardPrice)
	if err != nil {
		LogH5.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = card
	b.ResponseSuccess()
}
